package com.roundarch.www.ui;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.roundarch.www.model.Post;
import com.roundarch.www.model.SearchContent;
import com.roundarch.www.service.EntityService;

@Controller
@RequestMapping("/search")
public class SearchController {

	private EntityService entityService;
	private final File INDEX_DIR = new File("index");  

	private final Log logger = LogFactory.getLog(SearchController.class);
	private int startindex = 0;                     //the first index displayed on this page
    private int maxpage    = 50;                    //the maximum items displayed on this page
     
	public EntityService getEntityService() {
		return entityService;
	}

	public void setEntityService(EntityService entityService) {
		this.entityService = entityService;
	}
	
	@RequestMapping("/createIndex")
	public String createIndex(Model model,HttpServletRequest request){
		logger.info("createIndex method called");
		generateIndex();
		return null;
	}
	
	@RequestMapping("/searchResults")
	public String searchResults(Model model,@RequestParam("term") String term,HttpServletRequest request){
		logger.info("searchResults method called");
		List<SearchContent> results = searchResults(term);
		model.addAttribute("results", results);
		return null;
	}
    
	public void generateIndex(){
		logger.info("generateIndex method called");
		IndexWriter.MaxFieldLength mfl = new IndexWriter.MaxFieldLength(IndexWriter.DEFAULT_MAX_FIELD_LENGTH);
		try{
				Directory dir = FSDirectory.open(INDEX_DIR);
			
			   StandardAnalyzer analyzer = BeanUtils.instantiateClass(StandardAnalyzer.class);
			   IndexWriter writer = new IndexWriter(dir, analyzer, true ,mfl);
			   System.out.println("Indexing to directory '" + INDEX_DIR + "'...");
			   indexDocs(writer);
			   writer.optimize();
			   writer.close();
			} catch (Exception e) {
			   e.printStackTrace();
			}
		logger.info("generateIndex method finished");

	}
	
	void indexDocs(IndexWriter writer) throws Exception {
		logger.info("indexDocs method called");
		 List<Post> posts = entityService.listAll(Post.class);
	     for(Post p:posts){
	    	 Document d = new Document();
	 	     d.add(new Field("id", String.valueOf(p.getId()), Field.Store.YES, Field.Index.NO));
		     d.add(new Field("title", p.getTitle(), Field.Store.YES, Field.Index.ANALYZED));
		     d.add(new Field("body", p.getBody(),Field.Store.YES, Field.Index.ANALYZED));
		     writer.addDocument(d);
	     }    
		 logger.info("indexDocs method finished");
			
	}
	
	public List<SearchContent> searchResults(String word){
		logger.info("searchResults method called");
		List<SearchContent> results = new ArrayList<SearchContent>();
		try{
			String id = null;
			String title = null;
			String body = null;
			Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_29);  
			Directory dir = FSDirectory.open(INDEX_DIR);
			IndexReader reader = IndexReader.open(dir, true); // only searching, so read-only=true
	          
			Searcher searcher = new IndexSearcher(reader);
			Query query = new QueryParser(Version.LUCENE_29,"body",analyzer).parse(word);
			
			TopDocs hits = searcher.search(query,  maxpage + startindex);
			/*Hits hits = searcher.search(query);*/
			for (int i = 0; i < hits.totalHits; i++){
			   Document doc = searcher.doc(hits.scoreDocs[i].doc);                    //get the next document 
               id = doc.get("id");
               title = doc.get("title");
               body = doc.get("body");
			   logger.info(" Searched Ids = "+id + "###");
			   results.add(new SearchContent("/post/show?id="+id, title, body));
			}
		
		}catch(Exception e){
			e.printStackTrace();
		}
		logger.info("searchResults method finished");
		return results;
		
		
	}
}
